
package com.bango.android;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.telephony.TelephonyManager;

/**
 * @author GRZEGORZ
 *
 */

public class BangoLogger implements LocationListener {

	private LocationManager _locationManager;

	private Context _applicationContext;
	private String _applicationId;
	private String _userAgent;
	private String _userId;
	private TelephonyManager _telephonyManager;
	private NetworkInfo _networkInfo;

	private BangoProfile _bangoProfile;
	private ArrayList<BangoEvent> _appEvents;

	private boolean _logEvents = BangoConstants.SETTING_LOGEVENTS;
	private int _sessionResumePeriod = BangoConstants.SETTING_SESSION_RESUME_PERIOD;
	private boolean _useOfflineStorage = BangoConstants.SETTING_USEOFFLINESTORAGE;
	private boolean _persistDatabaseConnection = BangoConstants.SETTING_PERSIST_DATABASE_CONNECTION;
	private String _postURL = BangoConstants.SETTING_POST_URL;
	private boolean _findLocation = BangoConstants.SETTING_LOCATION_FIND;
	private int _maximumEventsPerProfile = BangoConstants.SETTING_MAXIMUM_EVENTS_PER_PROFILE;
	private String _applicationType = "";
	private String _applicationChannel = "";
	private String _applicationVersion = "";	
	private String _locationSource = "";
	private BangoDatabaseStorage _bangoDatabaseStorage;
	
	private String _identifierURL = BangoConstants.SETTING_IDENTIFIER_URL;
	private boolean _identifyBangoUser = BangoConstants.SETTING_IDENTIFY_BANGO_USER;
	private String _bangoUserId;
	
	private int _httpConnectionTimeout = BangoConstants.SETTING_HTTP_CONNECTION_TIMEOUT;
	private int _httpSoTimeout = BangoConstants.SETTING_HTTP_SO_TIMEOUT;
	
	public BangoLogger()
	{

	}

	public void LogEvents(boolean logEvents) {
		_logEvents = logEvents;
	}

	public boolean LogEvents() {
		return _logEvents;
	}

	public void UseOfflineStorage(boolean useOfflineStorage) {
		_useOfflineStorage = useOfflineStorage;
	}

	public boolean UseOfflineStorage() {
		return _useOfflineStorage;
	}

	public void SessionResumePeriod(int sessionResumePeriod) {
		_sessionResumePeriod = sessionResumePeriod;
	}

	public int SessionResumePeriod() {
		return _sessionResumePeriod;
	}

	public void ApplicationVersion(String applicationVersion) {
		_applicationVersion = applicationVersion;
	}

	public String ApplicationVersion() {
		return _applicationVersion;
	}

	public void ApplicationType(String applicationType) {
		_applicationType = applicationType;
	}

	public String ApplicationType() {
		return _applicationType;
	}

	public void ApplicationChannel(String applicationChannel) {
		_applicationChannel = applicationChannel;
	}

	public String ApplicationChannel() {
		return _applicationChannel;
	}

	public void UserId(String userId) {
		_userId = userId;
	}

	public String UserId() {
		return _userId;
	}

	public boolean PersistDatabaseConnection() {
		return _persistDatabaseConnection;
	}

	public void PersistDatabaseConnection(boolean persistDatabaseConnection) {
		_persistDatabaseConnection = persistDatabaseConnection;
	}

	public void PostURL(String postURL) {
		_postURL = postURL;
	}

	public String PostURL() {
		return _postURL;
	}

	public void FindLocation(boolean findLocation) {
		_findLocation = findLocation;
	}

	public boolean FindLocation() {
		return _findLocation;
	}

	public void MaximumEventsPerProfile(int maximumEventsPerProfile) {
		if (maximumEventsPerProfile > 0) {
			_maximumEventsPerProfile = maximumEventsPerProfile;
		}
	}

	public int MaximumEventsPerProfile() {
		return _maximumEventsPerProfile;
	}
	
	public String BangoUserId() {
		return _bangoUserId;
	}
	
	public void IdentifierURL(String identifierURL) {
		_identifierURL = identifierURL;
	}

	public String IdentifierURL() {
		return _identifierURL;
	}
	
	public void IdentifyBangoUser(boolean identifyBangoUser) {
		_identifyBangoUser = identifyBangoUser;
	}

	public boolean IdentifyBangoUser() {
		return _identifyBangoUser;
	}
	
	public void HttpConnectionTimeout(int httpConnectionTimeout) {
		_httpConnectionTimeout = httpConnectionTimeout;
	}

	public int HttpConnectionTimeout() {
		return _httpConnectionTimeout;
	}
	
	public void HttpSoTimeout(int httpSoTimeout) {
		_httpSoTimeout = httpSoTimeout;
	}

	public int HttpSoTimeout() {
		return _httpSoTimeout;
	}


	/**
	 * Initialises the logging system. This should be called when starting the
	 * application, and is normally done with the onStartSession call.
	 * 
	 * @param applicationContext
	 *            The application or service context object.
	 * @param userAgent
	 *            The user agent of the device.
	 * @param applicationId
	 *            The application Id of the application. This should be setup in
	 *            the Bango Management Tools prior to use.
	 * @param telephonyManager
	 * @param networkInfo
	 * @param synchronisationObject
	 * 			  Optional, instance used as synchronisation object
	 */
	public void InitLogger(Context applicationContext, String userAgent,
			String applicationId, TelephonyManager telephonyManager,
			NetworkInfo networkInfo, Object synchronisationObject) {
		double locationLatitude = 0;
		double locationLongitude = 0;
		double locationAltitude = 0;
		float locationAccuracy = 0;
			
		
		_applicationContext = applicationContext;
		_applicationId = applicationId;
		_userAgent = userAgent;

		_telephonyManager = telephonyManager;
		_networkInfo = networkInfo;

		if (_applicationVersion == null) {
			_applicationVersion = GetApplicationVersion();
		}

		if (_userId == null) {
			_userId = android.provider.Settings.Secure.getString(
					applicationContext.getContentResolver(),
					android.provider.Settings.Secure.ANDROID_ID)
					+ " - " + _telephonyManager.getSimOperator();
		}
		
		if (FindLocation())
		{
			Location deviceLocation = GetLocation();
	
			if (deviceLocation != null) {
				locationAccuracy = deviceLocation.getAccuracy();
				locationLatitude = deviceLocation.getLatitude();
				locationLongitude = deviceLocation.getLongitude();
				locationAltitude = deviceLocation.getAltitude();
			}
		}
		
		
		if (_useOfflineStorage) {
			_bangoDatabaseStorage = new BangoDatabaseStorage(_applicationContext, synchronisationObject);
			_bangoDatabaseStorage.PersistDatabaseConnection(_persistDatabaseConnection);
		}
		
		_bangoUserId = this.getBangoUserId(applicationId);
		
		
		_bangoProfile = new BangoProfile(BangoConstants.SDK_TYPE, BangoConstants.SDK_VERSION, _applicationId, _applicationType, _applicationChannel, _applicationVersion, _userId, _sessionResumePeriod, ConnectionType(), IsRoaming(), _locationSource, locationAltitude, locationLatitude, locationLongitude, locationAccuracy, _telephonyManager.getNetworkOperator(), _telephonyManager.getNetworkOperatorName(), _telephonyManager.getSimCountryIso(), _telephonyManager.getSimOperator(), BangoConstants.DEVICE_BUILD_BRAND, BangoConstants.DEVICE_BUILD_DEVICE, BangoConstants.DEVICE_BUILD_MODEL, BangoConstants.DEVICE_BUILD_PRODUCT, BangoConstants.DEVICE_BUILD_VERSION, BangoConstants.DEVICE_BUILD_ID, _telephonyManager.getNetworkType(), _bangoUserId);
		_appEvents = new ArrayList<BangoEvent>();
		
		if(_useOfflineStorage){
			_bangoDatabaseStorage.LogProfile(_bangoProfile);			
		}
	}

	/**
	 * Posts any stored events, with an option to post the current profile
	 * 
	 * @param notCurrentProfile
	 *            Whether or not the current profile should be posted.
	 * @param closeDatabase
	 *            Whether or not to close the database, this parameter is
	 *            ignored if offline storage is not being used
	 * @return Whether or not at least 1 profile and associated events were
	 *         posted successfully
	 */
	@SuppressWarnings("unchecked")
	public boolean PostEvents(boolean notCurrentProfile, boolean closeDatabase) {
		boolean returnValue = false;
		List<BangoProfile> bangoProfiles;
		BangoProfile bangoProfile;
		ArrayList<BangoEvent> appEvents;

		try
		{
			if (_useOfflineStorage) {
				if (null !=_bangoDatabaseStorage)
				{
					bangoProfiles = _bangoDatabaseStorage.GetProfilesForPost(notCurrentProfile, _applicationId, _bangoUserId);			
					
					for (Iterator<BangoProfile> bangoProfileIterator = bangoProfiles.iterator(); bangoProfileIterator.hasNext();) {
						bangoProfile = bangoProfileIterator.next();
						appEvents = _bangoDatabaseStorage.GetEventsForPost(bangoProfile.ProfileId());
						
						if (appEvents.size() > 0) {
							if (PostEvents(bangoProfile, appEvents)) {
								_bangoDatabaseStorage.UpdateEventsPosted(bangoProfile.ProfileId());
								returnValue = true;
							}
							else 
							{
								_bangoDatabaseStorage.UpdateEventsNotPosted(bangoProfile.ProfileId());											
							}
						} else {
							if (bangoProfile.ProfileId() != _bangoDatabaseStorage.ProfileId()) {
								_bangoDatabaseStorage.DeleteEventsPosted(bangoProfile.ProfileId());
							}
						}
					}
		
					if (closeDatabase) {
						CloseDatabase();
					}
				}
			} else {
				bangoProfile = new BangoProfile(_bangoProfile);
				appEvents = (ArrayList<BangoEvent>) _appEvents.clone();			
				_appEvents = new ArrayList<BangoEvent>();			
				returnValue = PostEvents(bangoProfile, appEvents);
				
				if (!returnValue) {
					_appEvents.addAll(appEvents);
				}
			}
		} catch (Exception ex) {
			returnValue = false;
		}
		return returnValue;
	}

	/**
	 * Posts the supplied profile and associated events to the specified url.
	 * 
	 * @param bangoProfile
	 *            The profile to post to the specified url.
	 * @param appEvents
	 *            The associated events to post the specified url.
	 * @return Whether or not the profile and associated events were posted
	 *         successfully.
	 */
	private synchronized boolean PostEvents(BangoProfile bangoProfile,
			ArrayList<BangoEvent> appEvents) {
		boolean returnValue = false;
		String responseMessage;
		DefaultHttpClient httpClient;
		HttpPost httpPost;
		JSONObject postJSONObject;
		JSONArray postEvents;
		
		try {
			if (_logEvents
					&& (!_telephonyManager.isNetworkRoaming() || IsWifiConnection())) {
				httpClient = CreateHttpClient();
				httpPost = new HttpPost(_postURL);
				
				
				httpPost.setHeader("Content-Type", "application/json");

				if (_userAgent != null && !_userAgent.equals("")) {
					httpPost.addHeader("User-Agent", _userAgent);
				}

				postJSONObject = bangoProfile.GetDeviceProfile();
				postEvents = new JSONArray();
				for (Iterator<BangoEvent> bangoEvent = appEvents.iterator(); bangoEvent
						.hasNext();) {					
					postEvents.put(bangoEvent.next().GetEventDetails());
				}

				postJSONObject.put("Events", postEvents);

				httpPost.setEntity(new StringEntity(postJSONObject.toString()));
				HttpResponse response = httpClient.execute(httpPost);
				
				responseMessage = EntityUtils.toString(response.getEntity());
				returnValue = responseMessage
						.startsWith(BangoConstants.POST_RESPONSE_SUCCESS);
			}

		} catch (Exception ex) {
			returnValue = false;
		}

		return returnValue;

	}

	/**
	 * Creates instance of the DefaultHttpClient. Sets connection and socket timeout. 
	 * @return
	 */
	private DefaultHttpClient CreateHttpClient()
	{
		DefaultHttpClient defaultHttpClient = null;
		HttpParams httpParams = new BasicHttpParams();
		
		HttpConnectionParams.setConnectionTimeout(httpParams, this.HttpConnectionTimeout());
		HttpConnectionParams.setSoTimeout(httpParams, this.HttpSoTimeout());

		defaultHttpClient =  new DefaultHttpClient(httpParams);
		
		String userAgent = _userAgent;
		if ((null == userAgent) || userAgent.equals(""))
		{
			userAgent = System.getProperty("http.agent");			
		}
				
		defaultHttpClient.getParams().setParameter("User-Agent", userAgent);
		return defaultHttpClient;
	}
	
	public String viewBatch() {
		JSONObject postJSONObject = null;
		JSONArray postEvents;
		List<BangoProfile> bangoProfiles;
		BangoProfile bangoProfile = null;
		ArrayList<BangoEvent> appEvents = null;
		try {
		
		bangoProfiles = _bangoDatabaseStorage.GetProfilesForPost(false, "", _bangoUserId);
		
		for (Iterator<BangoProfile> bangoProfileIterator = bangoProfiles.iterator(); bangoProfileIterator.hasNext();) {
			bangoProfile = bangoProfileIterator.next();
			if (bangoProfile.ProfileId() == _bangoDatabaseStorage.ProfileId()) {
				appEvents = _bangoDatabaseStorage.GetEventsForPost(bangoProfile.ProfileId());
				break;
			}
		}			
		
		if (null != bangoProfile)
		{
			postJSONObject = bangoProfile.GetDeviceProfile();
			
			postEvents = new JSONArray();
			for (Iterator<BangoEvent> bangoEvent = appEvents.iterator(); bangoEvent.hasNext();) {
				postEvents.put(bangoEvent.next().GetEventDetails());
			}
				
			postJSONObject.put("Events", postEvents);
		}
		
		} catch (Exception ex) {

		}
		if (null != postJSONObject)
		{
			return postJSONObject.toString();
		}
		return "";
	}

	/**
	 * Gets the application version from the application configuration.
	 * 
	 * @return The application version.
	 */
	private String GetApplicationVersion() {
		String returnValue = BangoConstants.UNKNOWN_VERSION;
		try {
			PackageInfo packageInfo = _applicationContext.getPackageManager().getPackageInfo(_applicationContext.getPackageName(), 0);
			returnValue = packageInfo.versionName;
			if ((returnValue == null || returnValue.equals("")) && packageInfo.versionCode != 0) {
				returnValue = Integer.toString(packageInfo.versionCode);
			}

		} catch (Exception ex) {
			returnValue = BangoConstants.UNKNOWN_VERSION;
			LogInternalErrorWarning(ex);
		}
		return returnValue;
	}

	/**
	 * Gets the connection type. If the connection is a WiFi connection this
	 * will be returned. Otherwise the operator connection type will be
	 * returned.
	 * 
	 * @return The connection type in integer value. This is converted to a
	 *         textual value on posting.
	 */
	private int ConnectionType() {
		if (_networkInfo == null) {
			return -1;
		}

		return _networkInfo.getType();
	}

	/**
	 * Gets whether or not the user is currently roaming.
	 * 
	 * @return Whether or not the user is currently roaming.
	 */
	private boolean IsRoaming() {
		return _telephonyManager.isNetworkRoaming();
	}

	/**
	 * Gets whether or not the user is currently using a WiFi connection.
	 * 
	 * @return Whether or not the user is currently using a WiFi connection.
	 */
	private boolean IsWifiConnection() {
		return ConnectionType() == ConnectivityManager.TYPE_WIFI;
	}

	/**
	 * Logs an event to the internal logging engine.
	 * 
	 * @param eventName
	 *            The name of the event to log.
	 * @param errorLevel
	 *            The error level of the event to log.
	 * @param eventValue
	 *            The value of the event to log.
	 * @param eventDetail
	 *            The detail of the event to log.
	 * @param errorId
	 *            The error Id of the event to log.
	 * @param eventParameters
	 *            Any custom parameters to log with events.
	 * @return the internal id of the event.
	 */
	private int LogEvent(String eventName, int errorLevel, String eventValue,
			String eventDetail, String errorId,
			Hashtable<String, String> eventParameters) {
		int returnValue = -1;
		Date eventTime = BangoStatic.GetUTCDate();
		Date eventLocalTime = new Date(System.currentTimeMillis());
		List<BasicNameValuePair> eventParametersPairs = null;
		String eventParameterName;
		BangoEvent bangoEvent;
		
		try {
			if (_logEvents) {
				if (eventParameters != null && !eventParameters.isEmpty()) {
					eventParametersPairs = new ArrayList<BasicNameValuePair>();
					for (Enumeration<String> eventParameterEnumerator = eventParameters.keys(); eventParameterEnumerator.hasMoreElements();) {
						eventParameterName = (String) eventParameterEnumerator.nextElement();
						eventParametersPairs.add(new BasicNameValuePair(eventParameterName, eventParameters.get(eventParameterName).toString()));
					}
				}
					
				bangoEvent = new BangoEvent(_appEvents.size(),
						ConnectionType(), _telephonyManager.getNetworkType(),
						errorLevel, eventName, eventDetail, eventValue,
						errorId, eventTime, eventLocalTime,
						eventParametersPairs);
				
				_appEvents.add(bangoEvent);
					
				if (_useOfflineStorage) {
					returnValue = _bangoDatabaseStorage.LogEvent(bangoEvent);
					if (_maximumEventsPerProfile > 0 && _appEvents.size() >= _maximumEventsPerProfile) {
						_bangoDatabaseStorage.LogProfile(_bangoProfile);
						_appEvents = new ArrayList<BangoEvent>();
					}
				} else {
					returnValue = _appEvents.size();
				}
		}
		} catch (Exception ex) {
		}
		return returnValue;
	}

	/**
	 * Logs an event to the internal logging engine.
	 * 
	 * @param eventName
	 *            The name of the event to log.
	 * @param eventValue
	 *            The value of the event to log.
	 * @param eventDetail
	 *            The detail of the event to log.
	 * @param eventParameters
	 *            Any custom parameters to log with events.
	 * @return The internal id of the event.
	 */
	public int LogEvent(String eventName, String eventValue,
			String eventDetail, Hashtable<String, String> eventParameters) {
		return LogEvent(eventName, BangoConstants.ERROR_NONE, eventValue,
				eventDetail, "", eventParameters);
	}

	/**
	 * Logs an error event to the internal logging engine.
	 * 
	 * @param errorId
	 *            The error Id of the event to log.
	 * @param errorClass
	 *            The class in which the error occurred.
	 * @param message
	 *            The error message.
	 * @param eventParameters
	 *            Any custom parameters to log with events.
	 * @return The internal id of the error.
	 */
	public int LogEventError(String errorId, String errorClass, String message,
			Hashtable<String, String> eventParameters) {
		return LogEvent(BangoSessionEvents.EVENT_ERROR,
				BangoConstants.ERROR_USER, errorClass, message, errorId,
				eventParameters);
	}

	/**
	 * Logs a critical internal error event to the internal logging engine.
	 * 
	 * @param ex
	 *            The error that was raised.
	 * @return The internal id of the error.
	 */
	public int LogInternalErrorCritical(Exception ex) {
		return LogInternalError(ex, BangoConstants.ERROR_INTERNAL_CRITICAL);
	}

	/**
	 * Logs a warning internal error event to the internal logging engine.
	 * 
	 * @param ex
	 *            The error that was raised.
	 * @return The internal id of the error.
	 */
	public int LogInternalErrorWarning(Exception ex) {
		return LogInternalError(ex, BangoConstants.ERROR_INTERNAL_WARNING);
	}

	/**
	 * Logs an internal error event to the internal logging engine.
	 * 
	 * @param ex
	 *            The error that was raised.
	 * @param errorLevel
	 *            The error level of the error (Warning/Critical)
	 * @return The internal id of the error.
	 */
	private int LogInternalError(Exception ex, int errorLevel) {
		return LogEvent("", errorLevel, ex.getMessage(), ex.getStackTrace()
				.toString(), "", null);
	}

	/**
	 * Initialises the chosen location provider.
	 * 
	 * @return The last known location. If this is not known known null is
	 *         returned.
	 */
	private Location GetLocation() {
		Location returnValue = null;
		Criteria criteria;
		if (_findLocation) {
			if ((_applicationContext
					.checkCallingOrSelfPermission(BangoConstants.PERMISSION_ACCESS_COARSE_LOCATION) == 0)
					|| (_applicationContext
							.checkCallingOrSelfPermission(BangoConstants.PERMISSION_ACCESS_FINE_LOCATION) == 0)) {
				_locationManager = (LocationManager) _applicationContext
						.getSystemService(Context.LOCATION_SERVICE);
				criteria = new Criteria();
				if (_applicationContext
						.checkCallingOrSelfPermission(BangoConstants.PERMISSION_ACCESS_FINE_LOCATION) == 0) {
					criteria.setAccuracy(Criteria.ACCURACY_FINE);
					_locationSource = BangoConstants.LOCATION_GPS;
				} else {
					criteria.setAccuracy(Criteria.ACCURACY_COARSE);
					_locationSource = BangoConstants.LOCATION_CELL;
				}
				
				criteria.setAltitudeRequired(false);
				criteria.setBearingRequired(false);
				criteria.setSpeedRequired(false);
				criteria.setCostAllowed(false);

				String bestProvider = _locationManager.getBestProvider(
						criteria, true);

				if (bestProvider != null) {
					returnValue = _locationManager
							.getLastKnownLocation(bestProvider);
					_locationManager.requestLocationUpdates(bestProvider,
							BangoConstants.LOCATION_MANAGER_MIN_TIME,
							BangoConstants.LOCATION_MANAGER_MIN_DISTANCE, this);
				}

			}
		}
		return returnValue;
	}

	/**
	 * Destroys the location finder.
	 */
	public void EndLocationUpdates() {
		if (_findLocation && _locationManager != null) {
			_locationManager.removeUpdates(this);
			_locationManager = null;
		}
	}

	/**
	 * Updates the profile with the new location.
	 * 
	 * @param location
	 *            The new location of the user.
	 */
	private void UpdateLocation(Location location) {
		EndLocationUpdates();
		
		if (null != _bangoProfile)
		{
			_bangoProfile.LocationSource(_locationSource);
			_bangoProfile.LocationLatitude(location.getLatitude());
			_bangoProfile.LocationLongitude(location.getLongitude());
			_bangoProfile.LocationAccuracy(location.getAccuracy());
			_bangoProfile.LocationAltitude(location.getAltitude());
		}
		if (_useOfflineStorage && (null != _bangoDatabaseStorage)) {					
			_bangoDatabaseStorage.UpdateProfileLocation(_locationSource,
					location.getLatitude(), location.getLongitude(),
					location.getAltitude(), location.getAccuracy());			
		}
	}

	/**
	 * Called when the location provider has been updated.
	 * 
	 * @param location
	 *            The new location of the user.
	 */
	@Override
	public synchronized void onLocationChanged(Location location) {
		if (_findLocation)
		{
			UpdateLocation(location);
		}
	}

	@Override
	public void onProviderDisabled(String provider) {

	}

	@Override
	public void onProviderEnabled(String provider) {

	}

	/**
	 * Called by the LocationProvider to which this listener is registered if
	 * the state of the LocationProvider has changed.
	 * 
	 * @param provider
	 *            The provider used to obtain the latest location.
	 * @param newState
	 *            The new state of the LocationProvider. This value is one of
	 *            the constants for the state defined in the LocationProvider
	 *            class.
	 */
	@Override
	public void onStatusChanged(String provider, int status, Bundle extras) {

	}

	public void CloseDatabase() {
		if (null != _bangoDatabaseStorage)
			_bangoDatabaseStorage.CloseDatabase(true);
	}
	
	private String getBangoUserId(String _bangoNumber)
	{
		String bangoUserId = null;
		BangoDatabaseStorage.ProfilePersistent profilePersistent = null;

		if(_identifyBangoUser){
			
			if(_useOfflineStorage) 
			{
				profilePersistent = _bangoDatabaseStorage.GetProfilePersistent();
				bangoUserId = profilePersistent.BangoUserId;
			}
						
			if((bangoUserId == null) || profilePersistent.Date.before(new Date(System.currentTimeMillis())))
			{
				HttpClient httpClient = CreateHttpClient();
				HttpGet httpGet = new HttpGet(_identifierURL + _bangoNumber);
		
				try {
					ResponseHandler<String> responseHandler=new BasicResponseHandler();
				    String responseBody = httpClient.execute(httpGet, responseHandler);
				    InputStream is = new ByteArrayInputStream(responseBody.getBytes("UTF-8"));
				    DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
					Document dom = builder.parse(is);
					if (dom.getDocumentElement().getElementsByTagName("userId").getLength() > 0)
					{
					    bangoUserId = dom.getDocumentElement().getElementsByTagName("userId").item(0).getChildNodes().item(0).getNodeValue();					
					}
				} catch (ClientProtocolException e) {
				} catch (IOException e) {
				} catch (ParserConfigurationException e) {
				} catch (FactoryConfigurationError e) {
				} catch (SAXException e) {
				}
			}
			if(bangoUserId != null) {
				bangoUserId = bangoUserId.trim();
				if(bangoUserId.equals("0")) bangoUserId = null;
			}
		}
		return bangoUserId;
	}
	
}
